import java.io.Serializable;
import java.util.ArrayList;
import java.util.AbstractCollection;

/**
 * @author Matt Lee, Michael Zipp
 * @version $Revision: 1.1 $
 */
public abstract class UserDatabase implements Serializable{
	public static final int USERNAME_SEARCH = 0;

	public static final int NAME_SEARCH = 1;
	
	public static final int PATIENT = 2;
	
	public static final int NURSE = 3;
	
	public static final int DOCTOR = 4;
	
	public static final int SYSTEM_ADMIN = 5;
	
	public static final int PHARMACIST = 6;
	//Changed these to AbstractCollection to fit with the 'optimal coding' protocol.
	
	static ArrayList<Patient> patientList = new ArrayList<Patient>();
	
	static ArrayList<Doctor> doctorList = new ArrayList<Doctor>();
	
	static ArrayList<Nurse> nurseList = new ArrayList<Nurse>();
	
	static ArrayList<SystemAdmin> adminList = new ArrayList<SystemAdmin>();
	
	static ArrayList<Pharmacist> pharmList = new ArrayList<Pharmacist>();

	/**
	 * Adds a new user into the database
	 * @param user User being added
	 * @param UserType Type of user being added to the system.
	 */
	static String addUser(User user, int UserType){
		ArrayList<User> usernameCheck = searchUser(user.username, USERNAME_SEARCH);
		if (usernameCheck.size() == 0) {
			//if()
			if (UserType == PATIENT) {
				if (patientList.isEmpty()) { //Added to fight off nullPointerException.
					patientList.add(new Patient(user));
					return "Patient added.";
				}//End
				else {
					patientList.add(new Patient(user));
					return "Patient added.";
				}
			} else if (UserType == NURSE) {
				if (nurseList.isEmpty()) {
					nurseList.add(new Nurse(user));
					return "Nurse added.";
				} else {
					nurseList.add(new Nurse(user));
					return "Nurse added.";
				}
			}

			else if (UserType == DOCTOR) {
				if (doctorList.isEmpty()) {
					doctorList.add(new Doctor(user));
					return "Doctor added.";
				} else {
					doctorList.add(new Doctor(user));
					return "Doctor added.";
				}
			} else if (UserType == SYSTEM_ADMIN) {
				if (adminList.isEmpty()) {
					adminList.add(new SystemAdmin(user));
					return "System Administrator added.";
				} else {
					adminList.add(new SystemAdmin(user));
					return "System Administrator added.";
				}
			} else if (UserType == PHARMACIST) {
				pharmList.add((Pharmacist) user);
				return "Pharmacist added.";
			} else{
				return "Invalid usertype.";
			}
		}
		else{
			return "Username Taken";
		}
	}
	
	/**
	 * Removes a user from the database.
	 * @param userName User to be removed
	 * @param UserType the int of what the user is.
	 */
	public static String removeUser(String userName, int UserType){
		if (UserType == PATIENT) {
			if(patientList.isEmpty()){
				return "There are no patients in the database.";
			}
			for (Patient p : patientList) {
				if (p.getUsername().equals(userName)){
					patientList.remove(p);
					return "Patient removed.";
				}
			}
		}
		else if (UserType == NURSE){
			if(nurseList.isEmpty()){
				return "There are no nurses in the database.";
			}
			for (Nurse n : nurseList) {
				if (n.getUsername().equals(userName)){
					nurseList.remove(n);
					return "Nurse removed.";
				}
			}
		}
		else if (UserType == DOCTOR){
			if(doctorList.isEmpty()){
				return "There are no doctors in the database.";
			}
			for (Doctor d : doctorList) {
				if (d.getUsername().equals(userName)){
					doctorList.remove(d);
					return "Doctor removed.";
				}
			}
		}
		else if (UserType == SYSTEM_ADMIN){
			if(adminList.isEmpty()){
				return "There are no admins in the database.";
			}
			for (SystemAdmin s : adminList) {
				if (s.getUsername().equals(userName) && (adminList.size() > 1)){
					adminList.remove(s);
					return "System Admin removed.";
				}
			}
		}
		else if (UserType == PHARMACIST){
			if(pharmList.isEmpty()){
				return "There are no pharmacists in the database.";
			}
			for (Pharmacist p : pharmList) {
				if (p.getUsername().equals(userName)){
					pharmList.remove(p);
					return "Pharmacist removed.";
				}
			}
		}
		return "Invalid usertype/username";
		
	
	}
	
	/**
	 * Runs a generic search for any user in the system.
	 * If <code>USERNAME_SEARCH</code> is active, it will return a size 1
	 * ArrayList with the user inside.
	 * If <code>NAME_SEARCH</code> is active, it will return an ArrayList with 
	 * all name matches inside.
	 * @param searchTerm Search Term to be found (either the User's username or name)
	 * @param searchType Type of search, either 
	 * <code>USERNAME_SEARCH</code> or 
	 * <code>NAME_SEARCH</code> 
	 * @return An ArrayList of Users matching the search term.
	 */
	public static ArrayList<User> searchUser(String searchTerm, int searchType){
		ArrayList<User> results = new ArrayList<User>();
		results.addAll(searchPatient(searchTerm, searchType));
		results.addAll(searchDoctor(searchTerm, searchType));
		results.addAll(searchNurse(searchTerm, searchType));
		results.addAll(searchAdmin(searchTerm, searchType));
		results.addAll(searchPharm(searchTerm, searchType));
		return results;
	}

	/**
	 * Searches for a Patient in the system.
	 * @param searchTerm Search Term to be found (either the Patient's username or name)
	 * @param searchType Type of search, either 
	 * <code>USERNAME_SEARCH</code> or 
	 * <code>NAME_SEARCH</code> 
	 * @return An array list of the results.
	 */
	public static ArrayList<Patient> searchPatient(String searchTerm, int searchType){
		ArrayList<Patient> results = new ArrayList<Patient>();
		for(Patient p : patientList){
			if(searchType == USERNAME_SEARCH){
				if(p.getUsername().equals(searchTerm)) results.add(p);
			}
			if(searchType == NAME_SEARCH){
				if(p.getName().contains(searchTerm)) results.add(p);
			}
		}
		return results;
	}
	
	/**
	 * Searches for a Doctor in the system.
	 * @param searchTerm Search Term to be found (either the Doctor's username or name)
	 * @param searchType Type of search, either 
	 * <code>USERNAME_SEARCH</code> or 
	 * <code>NAME_SEARCH</code> 
	 * @return An array list of the results.
	 */
	public static ArrayList<Doctor> searchDoctor(String searchTerm, int searchType) {
		ArrayList<Doctor> results = new ArrayList<Doctor>();
		for(Doctor p : doctorList){
			if(searchType == USERNAME_SEARCH){
				if(p.getUsername().equals(searchTerm)) results.add(p);
			}
			if(searchType == NAME_SEARCH){
				if(p.getName().contains(searchTerm)) results.add(p);
			}
		}
		return results;
	}
	
	/**
	 * Searches for a Nurse in the system.
	 * @param searchTerm Search Term to be found (either the Nurse's username or name)
	 * @param searchType Type of search, either 
	 * <code>USERNAME_SEARCH</code> or 
	 * <code>NAME_SEARCH</code> 
	 * @return An array list of the results.
	 */
	public static ArrayList<Nurse> searchNurse(String searchTerm, int searchType) {
		ArrayList<Nurse> results = new ArrayList<Nurse>();
		for(Nurse p : nurseList){
			if(searchType == USERNAME_SEARCH){
				if(p.getUsername().equals(searchTerm)) results.add(p);
			}
			if(searchType == NAME_SEARCH){
				if(p.getName().contains(searchTerm)) results.add(p);
			}
		}
		return results;
	}
	
	/**
	 * Searches for a System Administrator in the system.
	 * @param searchTerm Search Term to be found (either the Patient's username or name)
	 * @param searchType Type of search, either 
	 * <code>USERNAME_SEARCH</code> or 
	 * <code>NAME_SEARCH</code> 
	 * @return An array list of the results.
	 */
	public static ArrayList<SystemAdmin> searchAdmin(String searchTerm, int searchType){
		ArrayList<SystemAdmin> results = new ArrayList<SystemAdmin>();
		for(SystemAdmin p : adminList){
			if(searchType == USERNAME_SEARCH){
				if(p.getUsername().equals(searchTerm)) results.add(p);
			}
			if(searchType == NAME_SEARCH){
				if(p.getName().contains(searchTerm)) results.add(p);
			}
		}
		return results;
	}
	
	/**
	 * Searches for a Pharmacist in the system.
	 * @param searchTerm Search Term to be found 
	 * (either the Pharmacist's username or name)
	 * @param searchType Type of search, either 
	 * <code>USERNAME_SEARCH</code> or 
	 * <code>NAME_SEARCH</code> 
	 * @return An array list of the results.
	 */
	public static ArrayList<Pharmacist> searchPharm(String searchTerm, int searchType){
		ArrayList<Pharmacist> results = new ArrayList<Pharmacist>();
		for(Pharmacist p : pharmList){
			if(searchType == USERNAME_SEARCH){
				if(p.getUsername().equals(searchTerm)) results.add(p);
			}
			if(searchType == NAME_SEARCH){
				if(p.getName().contains(searchTerm)) results.add(p);
			}
		}
		return results;
	}
	
	/**
	 * Removes all users except one admin from the system.
	 * The last admin in the list is the last one remaining
	 */
	static void removeAll(){
		patientList.clear();
		doctorList.clear();
		nurseList.clear();
		pharmList.clear();
		while(adminList.size() > 1){
			User removed = adminList.get(0);
			adminList.remove(removed);
		}
	}
}